package com.heima.search.service.impl;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import com.heima.common.constants.search.SearchConstants;
import com.heima.es.service.EsService;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.search.dtos.UserSearchDTO;
import com.heima.model.search.vos.SearchArticleVO;
import com.heima.model.threadlocal.AppThreadLocalUtils;
import com.heima.model.user.pojos.ApUser;
import com.heima.search.service.ApUserSearchService;
import com.heima.search.service.ArticleSearchService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * @Author XHui
 * @Since 2024/3/16 14:21
 * @Version 1.0
 */
@Service
public class ArticleSearchServiceImpl implements ArticleSearchService {

    @Resource
    private EsService esService;

    @Value("${file.minio.readPath}")
    private String readPath;

    @Value("${file.oss.web-site}")
    private String webSite;

    @Override
    public ResponseResult search(UserSearchDTO userSearchDto) {
        int fromIndex = userSearchDto.getFromIndex();
        Integer equipmentId = userSearchDto.getEquipmentId();
        String searchWords = userSearchDto.getSearchWords();
        int pageNum = userSearchDto.getPageNum();
        int pageSize = userSearchDto.getPageSize();
        Integer entryId = userSearchDto.getEntryId();
        Date minBehotTime = userSearchDto.getMinBehotTime();
        // 1. 参数校验
        // 如果 minBehotTime 为空，则设置为当前时间
        if (userSearchDto.getMinBehotTime() == null) {
            userSearchDto.setMinBehotTime(new Date());
        }

        asyncSaveSearchRecord(userSearchDto);

        // 2. 创建搜素请求对象 SearchSourceBuilder
        SearchSourceBuilder searchBuilder = new SearchSourceBuilder();

        // 2.1 创建布尔查询对象，帮助我们组装多个条件
        // 2.1.1 创建bool查询对象
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        boolQuery.must(QueryBuilders
                .matchQuery("title", userSearchDto.getSearchWords()
                ));
        // 2.1.3 注：filter不参与es内部的相关度得分运算
        boolQuery.filter(
                QueryBuilders.rangeQuery("publishTime").lt(minBehotTime)
        );
        searchBuilder.query(boolQuery);

        // 2.2 构建高亮条件
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        // 2.2.1 设置那个字段高亮
        highlightBuilder.field("title");
        highlightBuilder.preTags("<font style='color: red; font-size: inherit;'>");
        highlightBuilder.postTags("</font>");
        searchBuilder.highlighter(highlightBuilder);

        // 2.3  构建排序条件
        searchBuilder.sort("publishTime", SortOrder.DESC);

        // 2.4 构建分页条件
        searchBuilder.from(0).size(pageSize);

        // 3. 执行搜索
        PageResponseResult pageResponseResult = esService.search(
                searchBuilder,
                SearchArticleVO.class,
                SearchConstants.SEARCH_ARTICLE_INDEX_NAME);

        // 4. 返回结果中的staticUrl需要拼接minio的readPath
        List<SearchArticleVO> searchArticleVOs =
                (List<SearchArticleVO>) pageResponseResult.getData();
        if (CollectionUtils.isNotEmpty(searchArticleVOs)) {
            searchArticleVOs = searchArticleVOs.stream().map(searchArticleVO -> {
                searchArticleVO.setStaticUrl(
                        readPath + searchArticleVO.getStaticUrl()
                );

                String images = searchArticleVO.getImages();
                if (StringUtils.isNotBlank(images)) {
                    String[] split = images.split(",");
                    images = Arrays.stream(split)
                            .map(s -> webSite + s)
                            .collect(Collectors.joining(","));
                }
                return searchArticleVO;
            }).collect(Collectors.toList());
        }
        return pageResponseResult;
    }

    @Resource
    private ApUserSearchService apUserSearchService;

    private void asyncSaveSearchRecord(UserSearchDTO userSearchDto) {
        //===================  记录搜索历史记录
        ApUser user = AppThreadLocalUtils.getUser();
        if (user != null) userSearchDto.setEntryId(user.getId());
        // 异步调用保存用户输入关键词记录
        apUserSearchService.insert(userSearchDto);
    }

    @Override
    public void saveArticleDoc(SearchArticleVO article) {
        esService.save(article, SearchConstants.SEARCH_ARTICLE_INDEX_NAME);
    }

    @Override
    public void deleteArticleDoc(String articleId) {
        esService.deleteById(articleId, SearchConstants.SEARCH_ARTICLE_INDEX_NAME);
    }
}
